package com.synesthesiaconsulting.gwt.resources.client;

import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA.
 * User: ageer
 * Date: Jul 24, 2008
 * Time: 6:37:34 PM
 * To change this template use File | Settings | File Templates.
 */
public class DirectorUnit implements IDirector {
    private Map<String, DirectorUnit> subDirectors = new HashMap<String, DirectorUnit>();
    private Map<String, IActionUnit> myActions = new HashMap<String, IActionUnit>();

    public DirectorUnit() { 

    }

    public DirectorUnit(IActionUnit selfAction) {
        myActions.put(SELF, selfAction);
        subDirectors.put(SELF, this);
    }

    public void applyAction(String action) {

        if (GWTUtils.isLastModule(action)) myActions.get(action).applyAction(null);
        else subDirectors.get(GWTUtils.firstModule(action)).applyAction(GWTUtils.restModule(action));
    }

    public void applyActionTo(String action, Object to) {
        if (GWTUtils.isLastModule(action)) myActions.get(action).applyAction(to);
        else subDirectors.get(GWTUtils.firstModule(action)).applyActionTo(GWTUtils.restModule(action),to);
    }
    public DirectorUnit addSubModule(String moduleName) {
        return addSubModule(moduleName, myActions.get(SELF));
    }
    public DirectorUnit addSubModule(String moduleName, IActionUnit selfAction) {
        if (GWTUtils.isLastModule(moduleName)) {
            DirectorUnit nxt = subDirectors.get(moduleName);
            if (nxt == null) {
                nxt = new DirectorUnit(selfAction);
                subDirectors.put(moduleName, nxt);
            }
            return nxt;
        } else {
            String me = GWTUtils.firstModule(moduleName);
            DirectorUnit nxt = subDirectors.get(me);
            if (nxt == null) {
                nxt = new DirectorUnit(selfAction);
                subDirectors.put(me, nxt);
            }
            DirectorUnit retVal = nxt.addSubModule(GWTUtils.restModule(moduleName), selfAction);
            return retVal;
        }
    }

    public void addAction(String action, IActionUnit actionUnit) {
        if (GWTUtils.isLastModule(action)) myActions.put(action, actionUnit);
        else subDirectors.get(GWTUtils.firstModule(action)).addAction(GWTUtils.restModule(action), actionUnit);
    }

    public void mapAction(String action, String mapTo) {
        IActionUnit actionTo = getAction(mapTo);
        addAction(action, actionTo);
    }

    public IActionUnit getAction(String action) {
        if (GWTUtils.isLastModule(action)) return myActions.get(action);
        else return subDirectors.get(GWTUtils.firstModule(action)).getAction(GWTUtils.restModule(action));
    }
    public IDirector getDirector(String name) {
        if (!name.endsWith(SELF)) name += "." + SELF;
        return getDirectorHelper(name);
    }

    

    protected IDirector getDirectorHelper(String name) {
        try {
            if (name.equals(SELF)) return subDirectors.get(name);
            else return subDirectors.get(GWTUtils.firstModule(name)).getDirector(GWTUtils.restModule(name));
        } catch (Exception e) {
            System.err.println("Error. Module not found: " + name);
            return null;
        }
    }

    public String toHTML() {
        return "<pre>" + toString() + "</pre>";
    }
    public String toString() {
        return toStringHelper("");

    }

    public String toStringHelper(String acc) {
        String ret = "";
        if (!myActions.isEmpty()) {
            Iterator<String> keys = myActions.keySet().iterator();
            while (keys.hasNext()) {
                String nxt = keys.next();
                IActionUnit a = myActions.get(nxt);

                ret += acc + "\t" + nxt + ": " + myActions.get(nxt) + "\n";
            }
        }
        if (!subDirectors.isEmpty()) {
            Iterator<String> keys = subDirectors.keySet().iterator();
            while (keys.hasNext()) {
                String nxt = keys.next();
                if (!nxt.equals(SELF)) {
                    ret += acc + "\t" + nxt + "\n";
                    ret += subDirectors.get(nxt).toStringHelper(acc+"\t");
                }
            }

        }
        return ret;
    }

}
